package zdream.pmfield.stage.buff.ailment;

import zdream.pmfield.data.foe.MoveAdditionalEffects;
import zdream.pmfield.stage.buff.foe.FoeStageBuff;
import zdream.pmfield.stage.director.HookType;
import zdream.pmfield.stage.director.Hooks;
import zdream.pmfield.stage.message.FoeAddBuffMessage;
import zdream.pmfield.stage.message.FoeRemoveBuffMessage;
import zdream.pmfield.stage.object.FoeActor;

/**
 * <p>同击晕 (Stunned)
 * <p>直接让对方下轮无法行动. 那一轮不再触发瞌睡、移动力回复等效果
 * 无法行动触发后, 下回合是临时眩晕免疫 (仅持续一轮).
 * <p>{@link WetBuff} 无法剔除该临时眩晕免疫效果.
 * </p>
 *
 * @author Zdream
 * @date 2023-12-03
 * @since 0.0.1
 */
public class FlinchBuff extends FoeStageBuff {
	public static final String CATEGORY = MoveAdditionalEffects.E_FLINCH;
	public static final String CATEGORY_TEMP_IMMUNITY = "flinchTempImmunity";

	public FlinchBuff(FoeActor target) {
		super(target);
	}

	@Override
	public void init() {
		preventSameBuffBeforeFoeReceiveBuff();
		onHook(HookType.BEFORE_FOE_TURN_START)
				.handle(this::targetIsStunned)
				.withPriority(-1000)
				.buildAndSave();
	}

	private void targetIsStunned(Hooks.HookContext rawContext) {
		Hooks.BeforeTurnHookContext context = rawContext.as();
		if (context.foe != this.target) {
			return;
		}

		context.allowAct = false;
		context.allowActRejectBy = this;

		target.removeBuff(this);
		pushMessage(new FoeRemoveBuffMessage(this));

		FlinchImmunity immunity = new FlinchImmunity(target);
		final FoeActor.ReceiveBuffReport report = target.receiveBuff(immunity);
		pushMessage(new FoeAddBuffMessage(report));
	}

	@Override
	public String getCategory() {
		return CATEGORY;
	}

	@Override
	public String toString() {
		return "害怕";
	}

	public static class FlinchImmunity extends FoeStageBuff {
		public FlinchImmunity(FoeActor target) {
			super(target);
		}

		@Override
		public void init() {
			// 允许同类效果共存
			onHook(HookType.BEFORE_FOE_TURN_START)
					.handle(this::destroyMySelf)
					.withPriority(-1000)
					.buildAndSave();
			onHook(HookType.BEFORE_FOE_RECEIVE_BUFF)
					.handle(this::beforeFoeReceiveBuff)
					.withPriority(-1)
					.buildAndSave();
		}

		private void destroyMySelf(Hooks.HookContext rawContext) {
			Hooks.BeforeTurnHookContext context = rawContext.as();
			if (context.foe != this.target) {
				return;
			}

			target.removeBuff(this);
			pushMessage(new FoeRemoveBuffMessage(this));
		}

		private void beforeFoeReceiveBuff(Hooks.HookContext rawContext) {
			Hooks.BeforeFoeReceiveBuffContext context = rawContext.as();
			final FoeStageBuff otherBuff = context.otherBuff;

			if (otherBuff.target != this.target) {
				return;
			}
			if (otherBuff.is(CATEGORY)) {
				context.abort();
			}
		}

		@Override
		public String getCategory() {
			return CATEGORY_TEMP_IMMUNITY;
		}

		@Override
		public String toString() {
			return "临时免疫害怕";
		}
	}
}
